package com.lzj.server.exceptions;

import cn.dev33.satoken.exception.NotLoginException;
import com.lzj.server.utils.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.MessageSourceResolvable;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.HandlerMethodValidationException;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

import java.util.stream.Collectors;

/**
 * 全局异常处理器
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(NotLoginException.class)
    public Result<?> handleNotLoginException(NotLoginException e) {
        String message = switch (e.getType()) {
            case NotLoginException.NOT_TOKEN -> "未提供登录凭证，请先登录";
            case NotLoginException.INVALID_TOKEN -> "无效的登录凭证";
            case NotLoginException.TOKEN_TIMEOUT -> "登录状态已过期，请重新登录";
            case NotLoginException.BE_REPLACED -> "您的账号在另一地点登录";
            case NotLoginException.KICK_OUT -> "您已被强制下线";
            default -> "当前未登录";
        };
        return Result.error(message);
    }

    // 空指针异常
    @ExceptionHandler(NullPointerException.class)
    public Result<String> npe(NullPointerException e) {
        log.error("空指针异常: ", e);
        return Result.error("系统错误：空指针异常");
    }

    // 参数类型转换失败
    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    public Result<String> typeMismatch(MethodArgumentTypeMismatchException e) {
        log.error("参数类型错误:", e);
        return Result.error("参数类型错误：" + e.getMessage());
    }

    // 请求参数缺失
    @ExceptionHandler(MissingServletRequestParameterException.class)
    public Result<String> missingParam(MissingServletRequestParameterException e) {
        log.error("缺少请求参数: ", e);
        return Result.error("缺少请求参数：" + e.getParameterName());
    }

    @ExceptionHandler(BaseException.class)
    public Result<String> bex(BaseException e) {
        return Result.error(e.getMessage());
    }


    // 数据校验异常处理
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Result<String> handleValidException(MethodArgumentNotValidException e) {
        String errorMsg = e.getBindingResult().getFieldErrors().stream()
                .map(DefaultMessageSourceResolvable::getDefaultMessage)
                .collect(Collectors.joining(", "));
        return Result.error("参数校验失败: " + errorMsg);
    }

    // 处理方法参数校验失败异常
    @ExceptionHandler(HandlerMethodValidationException.class)
    public Result<String> handleHandlerMethodValidationException(HandlerMethodValidationException ex) {
        String msg = ex.getAllValidationResults().stream()
                .flatMap(r -> r.getResolvableErrors().stream())
                .map(MessageSourceResolvable::getDefaultMessage) // 这里拿到 @NotBlank/@Email 的 message
                .collect(Collectors.joining("; "));
        return Result.error("参数校验失败：" + msg);
    }

    @ExceptionHandler(Exception.class)
    public Result<String> ex(Exception e) {
        log.error(e.getMessage(), e);
        String msg = ObjectUtils.isEmpty(e.getMessage()) ? e.toString() : e.getMessage();
        return Result.error(msg);
    }
}